// Copyright 2010, Vanya Davidenko.
// Используемая кодировка: UTF-8.

#ifndef LIBV_RDTSC_H_
#define LIBV_RDTSC_H_

#ifdef _WIN32
# ifndef __INTEL_COMPILER
#  include <intrin.h>
#  pragma intrinsic(__rdtsc)
# endif
typedef unsigned __int64 uint64_t;
#else
# include <stdint.h>
#endif


namespace libv
{

#ifdef _WIN32

inline volatile uint64_t rdtsc()
{
    return __rdtsc();
}



#else


# if defined(__i386__)

inline volatile uint64_t rdtsc()
{
    uint32_t tsc;
    asm(".byte 0x0f, 0x31" : "=A" (tsc));
    return tsc;
}


# elif ( defined(__amd64__) || defined(__x86_64__) )

inline volatile uint64_t rdtsc()
{
    uint32_t lo, hi;
    asm("rdtsc" : "=a" (lo), "=d" (hi));
    return static_cast<uint64_t>(lo) |
           ( static_cast<uint64_t>(hi) << 32 );
}


# elif ( defined(__powerpc__) || defined(__ppc__) )

inline volatile uint64_t rdtsc()
{
    uint32_t tbl, tbu0, tbu1;

    do
    {
        asm("mftbu %0" : "=r" (tbu0));
        asm("mftb  %0" : "=r" (tbl ));
        asm("mftbu %0" : "=r" (tbu1));
    }
    while ( tbu0 != tbu1 );

    return tbl;
}


# elif defined(__sparc__)

inline volatile uint64_t rdtsc()
{
    uint32_t tick;
    asm(".byte 0x83, 0x41, 0x00, 0x00");
    asm("mov   %%g1, %0" : "=r" (tick));
    return tick;
}


#elif defined(__alpha__)

inline volatile uint64_t rdtsc()
{
    uint32_t cc;
    asm("rpcc %0" : "=r" (cc));
    return cc & 0xFFFFFFFF;
}


#elif defined(__ia64__)

inline volatile uint64_t rdtsc()
{
    uint32_t itc;
    asm("mov %0 = ar.itc" : "=r" (itc));
    return itc;
}

#endif

#endif  // _WIN32

}  // libv

#endif  // LIBV_RDTSC_H_
